#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/uio.h>
#endif

#include "rdb_lib.h"
#include "msgbus_lib.h"
#include "base_lib.h"
#include "hdb_lib.h"
#include "usleep.h"

#include "sample_his_define.h"
#include "sample_his_struct.h"
#include "sample_his_extern.h"

#if !lint
static char Sccsid[] = {"%Z% %M% %I% %G%"};
#endif /* !lint */
/*
typedef	struct	_keyid_type
{
	int		record_id;
	short		column_id;
}	KEYID_TYPE;
*/
typedef struct	_query_curve_info
{
	short		graph_no;
	short		curve_no;
	short		app_no;
	KEYID_TYPE	curve_id;
	unsigned char	real_flag;
	int		start_time;
	int		end_time;
	int		time_pace;
	unsigned char	query_mode;
}	QUERY_CURVE_INFO;

extern class system_net_info dnet_i;
extern struct		app_buf_head	ah;
int query_one_curve(QUERY_CURVE_INFO query_curve_info, char **result_ptr, int *result_length);

int query_real_curve(char *buffer, app_buf_head ah)
{
	short		curve_number, graph_no;
	char		*cur_pointer;
	char		*result_link, *input_ptr, *send_ptr, *remain_ptr;
	QUERY_CURVE_INFO	*query_curve_info;
	int		result_length, input_size, send_size, remain_size;
	int		return_no, ret, i;

	GetBuffer gBuf(ah);

        graph_no=gBuf.get_short(buffer);
	cur_pointer = buffer + sizeof(short);
        curve_number=gBuf.get_short(cur_pointer);
	cur_pointer += sizeof(short);
	
	if (curve_number <= 0)
	{
		TRACE_INFO( "curve_number is 0. \n");
		printf("curve_number is 0. \n");
		return	0;
	}
	// check if the report length is correct or not
	if (ah.rhead.length != (2 * sizeof(short) + curve_number * (2 * sizeof(unsigned char) + 3 * sizeof(short) + 4 * sizeof(int))))
	{
		TRACE_ERROR( "curve_report length incorrect. \n");
		printf("curve_report length incorrect. \n");
		return	-1;
	}
	
	query_curve_info = (QUERY_CURVE_INFO *) malloc(curve_number * sizeof(QUERY_CURVE_INFO));
	
	// get the request report contents, saved as query_curve_info[i]
	int real_curve_number = 0;
	for (i = 0; i < curve_number; i++)
	{
		query_curve_info[real_curve_number].graph_no = graph_no;
                query_curve_info[real_curve_number].curve_no=gBuf.get_short(cur_pointer);
		cur_pointer += sizeof(short);
                query_curve_info[real_curve_number].app_no=gBuf.get_short(cur_pointer);
		cur_pointer += sizeof(short);
                query_curve_info[real_curve_number].curve_id.record_id=gBuf.get_int(cur_pointer);
		cur_pointer += sizeof(int);
                query_curve_info[real_curve_number].curve_id.column_id=gBuf.get_short(cur_pointer);
		cur_pointer += sizeof(short);
		memcpy(&query_curve_info[real_curve_number].real_flag, cur_pointer, sizeof(unsigned char));
		cur_pointer += sizeof(unsigned char);
                query_curve_info[real_curve_number].start_time=gBuf.get_int(cur_pointer);
		cur_pointer += sizeof(int);
                query_curve_info[real_curve_number].end_time=gBuf.get_int(cur_pointer);
		cur_pointer += sizeof(int);
                query_curve_info[real_curve_number].time_pace=gBuf.get_int(cur_pointer);
		cur_pointer += sizeof(int);
		memcpy(&query_curve_info[real_curve_number].query_mode, cur_pointer, sizeof(unsigned char));
		cur_pointer += sizeof(unsigned char);

		if(query_curve_info[real_curve_number].real_flag == 1)
			real_curve_number ++;
	}
//	printf("real_curve_number = %d curve_number=%d\n", real_curve_number, curve_number);
	// get each query result, and send report to the host who request this query
	for (i = 0; i < real_curve_number; i++)
	{
//	printf("%d: start_time=%d end=%d time_pace=%d\n", i, query_curve_info[i].start_time, query_curve_info[i].end_time, query_curve_info[i].time_pace);
		if(query_one_curve(query_curve_info[i], &result_link, &result_length) < 0)
			continue;
				
		ret = history_sample.dnet_send_message_by_pri_id(
					DNET_REPORT_POINT_TO_POINT,
					DNET_HISTORY_CURVE_ANSWER,
					ah.rhead.sour_host,
					ah.rhead.sour_process_name,
					result_link, result_length, 
					ah.rhead.process_pri_id);
			
		if (ret < 0)
		{
				TRACE_INFO( "result frame %d send err! \n", ret);
				printf("result frame %d send err! \n", ret);
		}
		free(result_link);
	}
	if (query_curve_info != NULL)
	{
		free(query_curve_info);
		query_curve_info = NULL;
	}

	return 1;
}
	
int WriteOneYcChange(YcChangeStru *pYcChangeStru, QUERY_CURVE_INFO query_curve_info, char *ptr_result_pointer, int &startpos, int &endpos)
{
	float float_val;
	unsigned char	is_null;
	char *cur_ptr = pYcChangeStru->buf;
	class GetBuffer getBuf;
	getBuf.set_buf_byte_order(pYcChangeStru->byte_order);

  		  	for (int order_no = 0; order_no < sizeof(struct package_head_stru)/sizeof(int);order_no ++) 
    			{
        			getBuf.buf_reorder(cur_ptr+sizeof(int)*order_no,sizeof(int));
    			}   

			package_head_stru  head_stru_ptr;
			memcpy((char* )&head_stru_ptr, cur_ptr, sizeof(package_head_stru));
			cur_ptr += sizeof(package_head_stru);

			int yc_id = -1;
			for(int loop=0; loop<head_stru_ptr.num; loop++)
			{
				yc_id = getBuf.get_int( cur_ptr );
				cur_ptr += sizeof(int);

				float_val = getBuf.get_float( cur_ptr );
				cur_ptr += sizeof(float);

				if(yc_id == query_curve_info.curve_id.record_id)
					break;
			}

			if(yc_id == query_curve_info.curve_id.record_id)
			{
				endpos = pYcChangeStru->iTime - query_curve_info.start_time;
			//	printf("got a yc: startpos=%d endpos=%d, yc_id=%d, val=%f\n", startpos, endpos, yc_id, float_val);

				for(int i=startpos; i<=endpos; i++)
				{
					is_null = 0;
					memcpy(ptr_result_pointer + i*(sizeof(char)+sizeof(float)), 
							&is_null, sizeof(char));
					memcpy(ptr_result_pointer + i*(sizeof(char)+sizeof(float)) + sizeof(char), 
							&float_val, sizeof(float));
				}
				startpos = endpos + 1;
			}
	return 1;
}

int GetYcDataFromFaultFile(QUERY_CURVE_INFO query_curve_info, char *ptr_result_pointer, int &startpos, int &endpos)
{
	int	fid ;
	char	filename[80];
	int	retval,count;
	struct  tm      *change_time;
	int sg_time = query_curve_info.time_pace;
    	change_time=localtime((const time_t*)&sg_time);

	sprintf(filename,"../sg_data/%04d%02d%02d_%02d%02d%02d.dat", 
			change_time->tm_year+1900,
			change_time->tm_mon+1,
            		change_time->tm_mday,
		        change_time->tm_hour,
		        change_time->tm_min,
		        change_time->tm_sec);
	fid = open( filename, O_RDONLY);
	if( fid == -1)
	{
		printf(" Can't open file :%s  \n",filename);
		return	-1;
	}

	char byte_order;
	read(fid, (char*)&byte_order, sizeof(char));
	GetBuffer gBuf;
	gBuf.set_buf_byte_order(byte_order);

	read(fid, (char*)&count, sizeof(int));
	gBuf.buf_reorder((char*)&count,  sizeof(int));
	if(count <=0 || count>1800)
	{
		printf("count err: %d\n", count);
		close(fid);
		return -1;
	}

	YcChangeStru pYcChangeStru;
	int i;
	for(i=0; i<count; i++)
	{
		YcChangeStru pYcChangeStru;
		if(read(fid, (char*)&pYcChangeStru.iTime, sizeof(int))<0) break;
		gBuf.buf_reorder((char*)&pYcChangeStru.iTime,  sizeof(int));
		if(pYcChangeStru.iTime > query_curve_info.end_time) 
			break;
		if(pYcChangeStru.iTime < query_curve_info.start_time)
			continue;
		if(read(fid, (char*)&pYcChangeStru.ms, sizeof(short))<0) break;
		gBuf.buf_reorder((char*)&pYcChangeStru.ms,  sizeof(short));
		if(read(fid, (char*)&pYcChangeStru.byte_order, sizeof(char))<0) break;
		if(read(fid, (char*)&pYcChangeStru.buf_len, sizeof(int))<0) break;
		gBuf.buf_reorder((char*)&pYcChangeStru.buf_len,  sizeof(int));
		if(pYcChangeStru.buf_len <=0 || pYcChangeStru.buf_len>100*1000)
			continue;
		pYcChangeStru.buf = (char*)malloc(pYcChangeStru.buf_len);
		if(read(fid, (char*)pYcChangeStru.buf, pYcChangeStru.buf_len)>=0) 
			WriteOneYcChange(&pYcChangeStru, query_curve_info, ptr_result_pointer, startpos, endpos);
		free(pYcChangeStru.buf);
	}
//	printf("GetYcDataFromFaultFile i=%d, count=%d\n", i, count);

	close(fid);
	return 1;
}

int GetYcDataFromRealCurveList(QUERY_CURVE_INFO query_curve_info, char *ptr_result_pointer, int &startpos, int &endpos)
{
	float float_val;
	unsigned char	is_null;
	Boolean b = g_YcRealCurveList.GoHead();
	if(b) {
		YcChangeStru *pYcChangeStru = g_YcRealCurveList.Object();
		while(g_YcRealCurveList.Count()>1 && pYcChangeStru) {
			if(pYcChangeStru->iTime > query_curve_info.end_time) 
			{
//			printf("g_YcRealCurveList iTime=%d end=%d\n", pYcChangeStru->iTime, query_curve_info.end_time);
				break;
			}
			if(pYcChangeStru->iTime < query_curve_info.start_time)
			{
//			printf("g_YcRealCurveList iTime=%d start_time=%d\n", pYcChangeStru->iTime, query_curve_info.start_time);
				if(g_YcRealCurveList.GoNext())
				{
					pYcChangeStru = g_YcRealCurveList.Object();
					continue;
				}
				else
					break;
			}
			WriteOneYcChange(pYcChangeStru, query_curve_info, ptr_result_pointer, startpos, endpos);

			pYcChangeStru = g_YcRealCurveList.Object();
			if(g_YcRealCurveList.GoNext())
				pYcChangeStru = g_YcRealCurveList.Object();
			else
				break;
		}
	}
	else
	{
//		printf("g_YcRealCurveList is empty\n");
		return 0;
	}
	return 1;
}

int query_one_curve(QUERY_CURVE_INFO query_curve_info, char **result_ptr, int *result_length)
{
	int		retcode;
	int		result_number;
	int		ptr_result_length, error_no;
	int		start_time, end_time;
	char		*result_link, *cur_pointer, *ptr_result, *ptr_result_pointer;
	char		sql_statement[1000], key_string[20], *tmp_string;
	char		*start_time_string, *end_time_string;
	unsigned char	is_null;
	char		*def_table;
	short		end_flag = 1;
	short		frame_no = 0;
	int		i, k;

	result_number = query_curve_info.end_time - query_curve_info.start_time + 1;
	if(result_number <=0 || result_number>1801) {
		printf("query_one_curve err: start=%d end=%d result_number=%d\n", query_curve_info.start_time, query_curve_info.end_time, result_number);
		return -1;
	}
	error_no = 0;
	ptr_result_length = 5 * sizeof(short) + 4 * sizeof(int) + result_number*(sizeof(char)+sizeof(float));
	ptr_result = (char *) malloc(ptr_result_length);
	ptr_result_pointer = ptr_result;
	memcpy(ptr_result_pointer, &end_flag, sizeof(short));
	ptr_result_pointer += sizeof(short);
	memcpy(ptr_result_pointer, &frame_no, sizeof(short));
	ptr_result_pointer += sizeof(short);
	memcpy(ptr_result_pointer, &query_curve_info.graph_no, sizeof(short));
	ptr_result_pointer += sizeof(short);
	memcpy(ptr_result_pointer, &query_curve_info.curve_no, sizeof(short));
	ptr_result_pointer += sizeof(short);
	memcpy(ptr_result_pointer, &query_curve_info.app_no, sizeof(short));
	ptr_result_pointer += sizeof(short);
	memcpy(ptr_result_pointer, &query_curve_info.start_time, sizeof(int));
	ptr_result_pointer += sizeof(int);
	memcpy(ptr_result_pointer, &query_curve_info.end_time, sizeof(int));
	ptr_result_pointer += sizeof(int);
	int interval = 1;
	memcpy(ptr_result_pointer, &interval, sizeof(int));
	ptr_result_pointer += sizeof(int);
	ptr_result_pointer += sizeof(int);

	int startpos = 0;
	int endpos = 0;
	float	float_val;

	if(query_curve_info.time_pace == 1)
		GetYcDataFromRealCurveList(query_curve_info, ptr_result_pointer, startpos, endpos);
	else
		GetYcDataFromFaultFile(query_curve_info, ptr_result_pointer, startpos, endpos);
		
	if(startpos == 0)
	{
		endpos = query_curve_info.end_time - query_curve_info.start_time;
//	printf("query_one_curve startpos=%d endpos=%d\n", startpos, endpos);	

		TableOp table(SCADA, YC_DEFINE_NO);
		yc_define_scada yc_stru;
		int ret = table.TableGet((char*)&query_curve_info.curve_id.record_id, (char*)&yc_stru, sizeof(yc_stru));
		if(ret < 0 || yc_stru.status==STATE_YC_INVALID){
			is_null = 1;
			for(int i=startpos; i<=endpos; i++)
			{
				memcpy(ptr_result_pointer + i*(sizeof(char)), &is_null, sizeof(char));
			}
		}
		else
		{
			float_val = yc_stru.yc_val;
			is_null = 0;
			for(int i=startpos; i<=endpos; i++)
			{
				memcpy(ptr_result_pointer + i*(sizeof(char)+sizeof(float)), 
								&is_null, sizeof(char));
				memcpy(ptr_result_pointer + i*(sizeof(char)+sizeof(float)) + sizeof(char), 
							&float_val, sizeof(float));
			}
		}
	}
	else
	{
		memcpy(&float_val, ptr_result_pointer + endpos*(sizeof(char)+sizeof(float)) + sizeof(char), sizeof(float));
		endpos = query_curve_info.end_time - query_curve_info.start_time;
//		printf("append a yc: startpos=%d endpos=%d, val=%f\n", startpos, endpos, float_val);
		is_null = 0;
		for(int i=startpos; i<=endpos; i++)
		{
			memcpy(ptr_result_pointer + i*(sizeof(char)+sizeof(float)), 
							&is_null, sizeof(char));
			memcpy(ptr_result_pointer + i*(sizeof(char)+sizeof(float)) + sizeof(char), 
							&float_val, sizeof(float));
		}

	}
		
	memcpy(ptr_result + 5 * sizeof(short) + 3 * sizeof(int), &result_number, sizeof(int));
	*result_ptr = ptr_result;
	*result_length = ptr_result_length;
//	printf("query_one_curve result_number=%d ptr_result_length=%d\n", result_number, ptr_result_length);
//	printf("val=%f\n", *(float*)(ptr_result + 5 * sizeof(short) + 4 * sizeof(int)+sizeof(char)));
	return 0;

}


